#include "business_cacert_update.h"

BusinessCaCerUpdate::BusinessCaCerUpdate()
{
}

BusinessCaCerUpdate::~BusinessCaCerUpdate()
{
}

BusinessCaCerUpdate &BusinessCaCerUpdate::getInstance()
{
    static BusinessCaCerUpdate instance;
    return instance;
}

void BusinessCaCerUpdate::init()
{
    getSdaCaCerOnce();
    return;
}

int BusinessCaCerUpdate::getSdaCaCerOnce()
{
    if (DC_SUCC != checkHttpHealth())
    {
        Log_Info("[BusinessCaCerUpdate] [getSdaCaCerOnce] checkHttpHealth failed...");
        return DC_FAIL;
    }

    if (DC_SUCC != getCaCerDownLoadLink())
    {
        Log_Info("[BusinessCaCerUpdate] [getSdaCaCerOnce] getCaCerDownLoadLink failed...");
        return DC_FAIL;
    }

    if (DC_SUCC != doDownLoadCaCerTask())
    {
        Log_Info("[BusinessCaCerUpdate] [getSdaCaCerOnce] doDownLoadCaCerTask failed...");
        return DC_FAIL;
    }

    Log_Info("[BusinessCaCerUpdate] [getSdaCaCerOnce] get cloud config success...");
    return DC_SUCC;
}

int BusinessCaCerUpdate::checkHttpHealth()
{
    //static uint8_t tokenTrynum = 0;
    //bool bGetToken = false;

    if (!comoprhttp.httpReqInit(STR_DOMAIN_SYS))
    {
        Log_Info("[BusinessCaCerUpdate] [checkHttpHealth] httpReqInit failed!");
        return DC_FAIL;
    }

    if (comoprhttp.hu_tokenMsg.empty())
    {
        Log_Info("[BusinessCaCerUpdate] [checkHttpHealth] hu_tokenMsg is empty!");
        return DC_FAIL;
    }

    Log_Info("[BusinessCaCerUpdate] [checkHttpHealth] comoprhttp init succ, hu_tokenMsg:{} ", comoprhttp.hu_tokenMsg); 
    return DC_SUCC;
}


int BusinessCaCerUpdate::getCaCerDownLoadLink()
{
    cloudResCatchBuff = "";
    std::string url = SRT_HTTPSPRE + comoprhttp.domainHost + SRT_URL_GETCACERLINK;

    // 设置http请求头
    map<string,string> http_header;
    http_header["Content-Type"] = "application/json;charset=UTF-8";
    http_header["Accept"] = "*/*";
    http_header["X-VCS-Hu-Token"] = comoprhttp.hu_tokenMsg;
    http_header["X-VCS-Timestamp"] = CommonOprTime::getTimestr();
    http_header["X-VCS-Nonce"] = CommonOprString::GetRandStr(4);

    // 设置消息body
    Json::Value parampostFiled;
    parampostFiled["versionNumber"] = "";
    Json::FastWriter writer;
    std::string postFiled = writer.write(parampostFiled);

    // http请求
    std::string responseBuff;
    if (comoprhttp.doHttpPostRequest(url, http_header, postFiled, 1, responseBuff))
    {
        cloudResCatchBuff = responseBuff;
        return DC_SUCC;
    }

    return DC_FAIL;
}


int BusinessCaCerUpdate::doDownLoadCaCerTask()
{
    Json::Reader reader;
    Json::Value root;
    if (!reader.parse(cloudResCatchBuff, root))
    {
        Log_Info("[BusinessCaCerUpdate] [doDownLoadCaCerTask] parse error:{}", cloudResCatchBuff);
        return false;
    }
    Json::Value data = root["data"];
    if (data.empty())
    {
        Log_Info("[BusinessCaCerUpdate] [doDownLoadCaCerTask] data empty:{}", cloudResCatchBuff);
        return false;
    }
    string downloadAddress = JsonToValue<string>(data["downloadAddress"]);

    // 设置http请求头
    map<string,string> http_header;
    http_header["Content-Type"] = "application/json;charset=UTF-8";
    http_header["Accept"] = "*/*";

    // http请求
    std::string responseBuff;
    if (comoprhttp.doHttpGetRequest(downloadAddress, http_header, 0, responseBuff))
    {
        updateLocalCaCer(responseBuff);
        return DC_SUCC;
    }

    return DC_FAIL;
}


int BusinessCaCerUpdate::updateLocalCaCer(string &caCerBuff)
{
    string factoryfile = global_data::g_httpCaFilePath + global_data::g_rootCaCertPem;
    string factoryCaCer;
    CommonOprSystem::readFileAllOnce(factoryfile, factoryCaCer);

    string localfile = global_data::g_SdaCaFilePath + global_data::g_rootCaCertPem;
    string localCaCer;
    CommonOprSystem::readFileAllOnce(localfile, localCaCer);

    vector<string> v_caCer;
    caCerBuffParse(factoryCaCer, v_caCer);
    caCerBuffParse(localCaCer, v_caCer);
    caCerBuffParse(caCerBuff, v_caCer);

    string caCerBuffWrite;
    caCerBuffCreate(caCerBuffWrite, v_caCer);
    Log_Info("[BusinessCaCerUpdate] [updateLocalCaCer] caCerBuffWrite:{}", caCerBuffWrite);
    if( !caCerBuffWrite.empty() )
    {
        CommonOprSystem::writeStringBuffToFile(localfile, caCerBuffWrite);
    }
    return DC_SUCC;
}


int BusinessCaCerUpdate::caCerBuffParse(string &caCerBuff, vector<string> &v_caCer)
{
    string cerBeginFlag = "-----BEGIN CERTIFICATE-----";
    string cerEndFlag = "-----END CERTIFICATE-----";

    string stringLeft = caCerBuff;
    size_t posStart = stringLeft.find(cerBeginFlag);
    size_t posEnd = stringLeft.find(cerEndFlag);

    while(posStart != stringLeft.npos && posEnd != stringLeft.npos)
    {
        size_t copyStart = posStart + cerBeginFlag.size();
        string caCerStr = stringLeft.substr(copyStart, posEnd-copyStart);

        if(NotContain_List(v_caCer, caCerStr))
        {
            v_caCer.push_back(caCerStr);
        }

        stringLeft = stringLeft.substr(posEnd+cerEndFlag.size());
        posStart = stringLeft.find(cerBeginFlag);
        posEnd = stringLeft.find(cerEndFlag);
    }

    return DC_SUCC;
}

int BusinessCaCerUpdate::caCerBuffCreate(string &caCerBuff, vector<string> &v_caCer)
{
    string cerBeginFlag = "-----BEGIN CERTIFICATE-----";
    string cerEndFlag = "-----END CERTIFICATE-----";

    for(string &caCerStr: v_caCer)
    {
        caCerBuff = caCerBuff + cerBeginFlag + caCerStr + cerEndFlag + "\n\n";
    }

    return DC_SUCC;
}




